package com.zbcn.GOF.singleton;

/**
 *  @title SingletonLanHan
 *  @Description 单例模式懒汉式
 *  @author zbcn8
 *  @Date 2020/6/16 9:36
 */
public class SingletonLanHan {

    /**
     * 单例模式的懒汉式[线程不安全，不可用]
     */
    private static SingletonLanHan singletonLanHan;

    private SingletonLanHan() {
    }

    public SingletonLanHan getSingletonLanHan(){
        if(singletonLanHan == null){//这里线程不安全,可能出现两个不同的实例
            //创建对象和赋值在内存模型中分为两步:线程不安全
            singletonLanHan = new SingletonLanHan();
        }
        return singletonLanHan;
    }

    private static SingletonLanHan singletonLanHanTwo;

    //懒汉式线程安全的:[线程安全，效率低不推荐使用]

    /**
     * 效率太低了，每个线程在想获得类的实例时候，执行getInstance()方法都要进行同步。
     *  而其实这个方法只执行一次实例化代码就够了，
     *  后面的想获得该类实例，直接return就行了。方法进行同步效率太低要改进。
     * @return
     */
    public static synchronized SingletonLanHan getSingletonLanHanTwo() {
        if (singletonLanHanTwo == null) { // 这里线程是不安全的,可能得到两个不同的实例
            singletonLanHanTwo = new SingletonLanHan();
        }
        return singletonLanHanTwo;
    }

    private static SingletonLanHan instanceThree = null;

    /**
     * 单例模式懒汉式[线程不安全，不可用]
     * <p>
     * 虽然加了锁，但是等到第一个线程执行new Singleton()s时，
     * 另一个进入if语句的线程同样会实例化另外一个Singleton对象，线程不安全的原理跟3类似。
     */
    public static SingletonLanHan getSingletonLanHanThree() {
        if (instanceThree == null) {
            synchronized (SingletonLanHan.class) {// 线程不安全
                instanceThree = new SingletonLanHan();
            }
        }
        return instanceThree;
    }

    private static SingletonLanHan singletonLanHanFour;

    /**
     * 单例模式懒汉式双重校验锁[推荐用]
     * 懒汉式变种,属于懒汉式的最好写法,保证了:延迟加载和线程安全
     * @return
     */
    public static SingletonLanHan getSingletonLanHanFour() {
        if (singletonLanHanFour == null) {
            synchronized (SingletonLanHan.class) {
                if (singletonLanHanFour == null) {
                    singletonLanHanFour = new SingletonLanHan();
                }
            }
        }
        return singletonLanHanFour;
    }
}
